#include "LobbyDBSpec.h"
#include "BitStream.h"
#include "StringCompressor.h"
#include "RakAssert.h"
#include "STDStringCompressor.h"

using namespace LobbyDBSpec;

static const int MAX_BINARY_DATA_LENGTH=10000000;

CreateUser_Data::CreateUser_Data() {binaryData=0; binaryDataLength=0;}
CreateUser_Data::~CreateUser_Data()
{
	if (binaryData)
		delete [] binaryData;
}
void CreateUser_Data::Serialize(RakNet::BitStream *bs)
{
	stringCompressor->EncodeString(handle.c_str(), 4096, bs, 0);
	SerializeCCInfo(bs);
	SerializeBinaryData(bs);
	SerializePersonalInfo(bs);
	SerializeEmailAddr(bs);
	SerializePassword(bs);
	SerializeCaptions(bs);
	SerializeOtherInfo(bs);
	SerializePermissions(bs);
	SerializeAccountNumber(bs);
	SerializeAdminLevel(bs);
	SerializeAccountBalance(bs);
}
bool CreateUser_Data::Deserialize(RakNet::BitStream *bs)
{
	STDDecodeString(&handle, 4096, bs, 0);
	DeserializeCCInfo(bs);
	DeserializeBinaryData(bs);
	DeserializePersonalInfo(bs);
	DeserializeEmailAddr(bs);
	DeserializePassword(bs);
	DeserializeCaptions(bs);
	DeserializeOtherInfo(bs);
	DeserializePermissions(bs);
	DeserializeAccountNumber(bs);
	DeserializeAdminLevel(bs);
	return DeserializeAccountBalance(bs);

}
void CreateUser_Data::SerializeCCInfo(RakNet::BitStream *bs)
{
	stringCompressor->EncodeString(billingAddress1.c_str(), 4096, bs, 0);
	stringCompressor->EncodeString(billingAddress2.c_str(), 4096, bs, 0);
	stringCompressor->EncodeString(billingCity.c_str(), 4096, bs, 0);
	stringCompressor->EncodeString(billingState.c_str(), 4096, bs, 0);
	stringCompressor->EncodeString(billingProvince.c_str(), 4096, bs, 0);
	stringCompressor->EncodeString(billingCountry.c_str(), 4096, bs, 0);
	stringCompressor->EncodeString(billingZipCode.c_str(), 4096, bs, 0);
	stringCompressor->EncodeString(creditCardNumber.c_str(), 4096, bs, 0);
	stringCompressor->EncodeString(creditCardExpiration.c_str(), 4096, bs, 0);
	stringCompressor->EncodeString(creditCardCVV.c_str(), 4096, bs, 0);
}
void CreateUser_Data::SerializeBinaryData(RakNet::BitStream *bs)
{
	bs->WriteAlignedBytesSafe(binaryData,binaryDataLength,MAX_BINARY_DATA_LENGTH);
}
void CreateUser_Data::SerializePersonalInfo(RakNet::BitStream *bs)
{
	stringCompressor->EncodeString(firstName.c_str(), 4096, bs, 0);
	stringCompressor->EncodeString(middleName.c_str(), 4096, bs, 0);
	stringCompressor->EncodeString(lastName.c_str(), 4096, bs, 0);
	stringCompressor->EncodeString(race.c_str(), 4096, bs, 0);
	stringCompressor->EncodeString(sex.c_str(), 4096, bs, 0);
	stringCompressor->EncodeString(homeAddress1.c_str(), 4096, bs, 0);
	stringCompressor->EncodeString(homeAddress2.c_str(), 4096, bs, 0);
	stringCompressor->EncodeString(homeCity.c_str(), 4096, bs, 0);
	stringCompressor->EncodeString(homeState.c_str(), 4096, bs, 0);
	stringCompressor->EncodeString(homeProvince.c_str(), 4096, bs, 0);
	stringCompressor->EncodeString(homeCountry.c_str(), 4096, bs, 0);
	stringCompressor->EncodeString(homeZipCode.c_str(), 4096, bs, 0);
	stringCompressor->EncodeString(dateOfBirth.c_str(), 4096, bs, 0);
}
void CreateUser_Data::SerializeEmailAddr(RakNet::BitStream *bs)
{
	stringCompressor->EncodeString(emailAddress.c_str(), 4096, bs, 0);
}
void CreateUser_Data::SerializePassword(RakNet::BitStream *bs)
{
	stringCompressor->EncodeString(password.c_str(), 4096, bs, 0);
	stringCompressor->EncodeString(passwordRecoveryQuestion.c_str(), 4096, bs, 0);
	stringCompressor->EncodeString(passwordRecoveryAnswer.c_str(), 4096, bs, 0);
}
void CreateUser_Data::SerializeCaptions(RakNet::BitStream *bs)
{
	stringCompressor->EncodeString(caption1.c_str(), 4096, bs, 0);
	stringCompressor->EncodeString(caption2.c_str(), 4096, bs, 0);
	stringCompressor->EncodeString(caption3.c_str(), 4096, bs, 0);
}
void CreateUser_Data::SerializeOtherInfo(RakNet::BitStream *bs)
{
	stringCompressor->EncodeString(sourceIPAddress.c_str(), 4096, bs, 0);
}
void CreateUser_Data::SerializeAccountNumber(RakNet::BitStream *bs)
{
	bs->Write(accountNumber);
}
void CreateUser_Data::SerializeAdminLevel(RakNet::BitStream *bs)
{
	stringCompressor->EncodeString(adminLevel.c_str(), 4096, bs, 0);
}
void CreateUser_Data::SerializeAccountBalance(RakNet::BitStream *bs)
{
	bs->Write(accountBalance);
}
void CreateUser_Data::SerializePermissions(RakNet::BitStream *bs)
{
	stringCompressor->EncodeString(permissions.c_str(), 4096, bs, 0);
}
bool CreateUser_Data::DeserializeCCInfo(RakNet::BitStream *bs)
{
	STDDecodeString(&billingAddress1, 4096, bs, 0);
	STDDecodeString(&billingAddress2, 4096, bs, 0);
	STDDecodeString(&billingCity, 4096, bs, 0);
	STDDecodeString(&billingState, 4096, bs, 0);
	STDDecodeString(&billingProvince, 4096, bs, 0);
	STDDecodeString(&billingCountry, 4096, bs, 0);
	STDDecodeString(&billingZipCode, 4096, bs, 0);
	STDDecodeString(&creditCardNumber, 4096, bs, 0);
	STDDecodeString(&creditCardExpiration, 4096, bs, 0);
	return STDDecodeString(&creditCardCVV, 4096, bs, 0);
}
bool CreateUser_Data::DeserializeBinaryData(RakNet::BitStream *bs)
{
	return bs->ReadAlignedBytesSafeAlloc(&binaryData,binaryDataLength, MAX_BINARY_DATA_LENGTH);
}
bool CreateUser_Data::DeserializePersonalInfo(RakNet::BitStream *bs)
{
	STDDecodeString(&firstName, 4096, bs, 0);
	STDDecodeString(&middleName, 4096, bs, 0);
	STDDecodeString(&lastName, 4096, bs, 0);
	STDDecodeString(&race, 4096, bs, 0);
	STDDecodeString(&sex, 4096, bs, 0);
	STDDecodeString(&homeAddress1, 4096, bs, 0);
	STDDecodeString(&homeAddress2, 4096, bs, 0);
	STDDecodeString(&homeCity, 4096, bs, 0);
	STDDecodeString(&homeState, 4096, bs, 0);
	STDDecodeString(&homeProvince, 4096, bs, 0);
	STDDecodeString(&homeCountry, 4096, bs, 0);
	STDDecodeString(&homeZipCode, 4096, bs, 0);
	return STDDecodeString(&dateOfBirth, 4096, bs, 0);
}
bool CreateUser_Data::DeserializeEmailAddr(RakNet::BitStream *bs)
{
	return STDDecodeString(&emailAddress, 4096, bs, 0);
}
bool CreateUser_Data::DeserializePassword(RakNet::BitStream *bs)
{
	STDDecodeString(&password, 4096, bs, 0);
	STDDecodeString(&passwordRecoveryQuestion, 4096, bs, 0);
	return STDDecodeString(&passwordRecoveryAnswer, 4096, bs, 0);
}
bool CreateUser_Data::DeserializeCaptions(RakNet::BitStream *bs)
{
	STDDecodeString(&caption1, 4096, bs, 0);
	STDDecodeString(&caption2, 4096, bs, 0);
	return STDDecodeString(&caption3, 4096, bs, 0);
}
bool CreateUser_Data::DeserializeOtherInfo(RakNet::BitStream *bs)
{
	bs->Read(accountNumber);
	return STDDecodeString(&sourceIPAddress, 4096, bs, 0);
}
bool CreateUser_Data::DeserializeAccountNumber(RakNet::BitStream *bs)
{
	return bs->Read(accountNumber);
}
bool CreateUser_Data::DeserializeAdminLevel(RakNet::BitStream *bs)
{
	return STDDecodeString(&adminLevel, 4096, bs, 0);
}
bool CreateUser_Data::DeserializeAccountBalance(RakNet::BitStream *bs)
{
	return bs->Read(accountBalance);
}
bool CreateUser_Data::DeserializePermissions(RakNet::BitStream *bs)
{
	return STDDecodeString(&permissions, 4096, bs, 0);
}
void UpdateUser_Data::Serialize(RakNet::BitStream *bs)
{
	SerializeBooleans(bs);
	if (updateCCInfo)
		input.SerializeCCInfo(bs);
	if (updateBinaryData)
		input.SerializeBinaryData(bs);
	if (updatePersonalInfo)
		input.SerializePersonalInfo(bs);
	if (updateEmailAddr)
		input.SerializeEmailAddr(bs);
	if (updatePassword)
		input.SerializePassword(bs);
	if (updateCaptions)
		input.SerializeCaptions(bs);
	if (updateOtherInfo)
		input.SerializeOtherInfo(bs);
	if (updatePermissions)
		input.SerializePermissions(bs);
	if (updateAccountNumber)
		input.SerializeAccountNumber(bs);
	if (updateAdminLevel)
		input.SerializeAdminLevel(bs);
	if (updateAccountBalance)
		input.SerializeAccountBalance(bs);
}
bool UpdateUser_Data::Deserialize(RakNet::BitStream *bs)
{
	return Deserialize(bs, &input, true);
}
bool UpdateUser_Data::Deserialize(RakNet::BitStream *bs, CreateUser_Data *output, bool deserializeBooleans)
{
	bool ret;
	if (deserializeBooleans)
		ret = DeserializeBooleans(bs);
	else
		ret=true;
	if (updateCCInfo)
		ret=output->DeserializeCCInfo(bs);
	if (updateBinaryData)
		ret=output->DeserializeBinaryData(bs);
	if (updatePersonalInfo)
		ret=output->DeserializePersonalInfo(bs);
	if (updateEmailAddr)
		ret=output->DeserializeEmailAddr(bs);
	if (updatePassword)
		ret=output->DeserializePassword(bs);
	if (updateCaptions)
		ret=output->DeserializeCaptions(bs);
	if (updateOtherInfo)
		ret=output->DeserializeOtherInfo(bs);
	if (updatePermissions)
		ret=output->DeserializePermissions(bs);
	if (updateAccountNumber)
		ret=output->DeserializeAccountNumber(bs);
	if (updateAdminLevel)
		ret=output->DeserializeAdminLevel(bs);
	if (updateAccountBalance)
		ret=output->DeserializeAccountBalance(bs);
	return ret;
}
void UpdateUser_Data::SerializeBooleans(RakNet::BitStream *bs)
{
	bs->Write(updateCCInfo);
	bs->Write(updateBinaryData);
	bs->Write(updatePersonalInfo);
	bs->Write(updateEmailAddr);
	bs->Write(updatePassword);
	bs->Write(updateCaptions);
	bs->Write(updateOtherInfo);
	bs->Write(updatePermissions);
	bs->Write(updateAccountNumber);
	bs->Write(updateAdminLevel);
	bs->Write(updateAccountBalance);
}
bool UpdateUser_Data::DeserializeBooleans(RakNet::BitStream *bs)
{
	bs->Read(updateCCInfo);
	bs->Read(updateBinaryData);
	bs->Read(updatePersonalInfo);
	bs->Read(updateEmailAddr);
	bs->Read(updatePassword);
	bs->Read(updateCaptions);
	bs->Read(updateOtherInfo);
	bs->Read(updatePermissions);
	bs->Read(updateAccountNumber);
	bs->Read(updateAdminLevel);
	return bs->Read(updateAccountBalance);
}
SendEmail_Data::SendEmail_Data() 
{
	attachment=0; attachmentLength=0;
}
SendEmail_Data::~SendEmail_Data()
{
	if (attachment)
		delete [] attachment;
}
void SendEmail_Data::Serialize(RakNet::BitStream *bs)
{
	bs->Write(id.hasUserId);
	bs->Write(id.userId);
	stringCompressor->EncodeString(id.userHandle.c_str(), 512, bs, 0);
	bs->Write(to.Size());
	unsigned i;
	for (i=0; i < to.Size(); i++)
	{
		bs->Write(to[i].hasUserId);
		if (to[i].hasUserId)
			bs->Write(to[i].userId);
		else
			stringCompressor->EncodeString(to[i].userHandle.c_str(), 512, bs, 0);
	}
	stringCompressor->EncodeString(subject.c_str(), 4096, bs, 0);
	stringCompressor->EncodeString(body.c_str(), 4096, bs, 0);
	bs->WriteAlignedBytesSafe(attachment, attachmentLength,MAX_BINARY_DATA_LENGTH);
	bs->Write(initialSenderStatus);
	bs->Write(initialRecipientStatus);
	bs->Write(status);
	bs->Write(creationTime);
	bs->Write(emailMessageID);
	bs->Write(wasOpened);
}
bool SendEmail_Data::Deserialize(RakNet::BitStream *bs)
{
	bs->Read(id.hasUserId);
	bs->Read(id.userId);
	STDDecodeString(&id.userHandle, 512, bs, 0);
	to.Clear(true);
	unsigned toSize;
	bs->Read(toSize);
	unsigned i;
	UserIdOrHandle uioh;
	for (i=0; i < toSize; i++)
	{
		bs->Read(uioh.hasUserId);
		if (uioh.hasUserId)
			bs->Read(uioh.userId);
		else
			STDDecodeString(&uioh.userHandle, 512, bs, 0);
		to.Insert(uioh);
	}
	STDDecodeString(&subject, 4096, bs, 0);
	STDDecodeString(&body, 4096, bs, 0);
	bs->ReadAlignedBytesSafeAlloc(&attachment, attachmentLength,MAX_BINARY_DATA_LENGTH);
	bs->Read(initialSenderStatus);
	bs->Read(initialRecipientStatus);
	bs->Read(status);
	bs->Read(creationTime);
	bs->Read(emailMessageID);
	return bs->Read(wasOpened);
}
GetAccountNotes_Data::~GetAccountNotes_Data()
{
	for (unsigned i=0; i < accountNotes.Size(); i++)
		accountNotes[i]->Deref();
}
GetFriends_Data::~GetFriends_Data()
{
	for (unsigned i=0; i < friends.Size(); i++)
		friends[i]->Deref();
}
GetIgnoreList_Data::~GetIgnoreList_Data()
{
	for (unsigned i=0; i < ignoredUsers.Size(); i++)
		ignoredUsers[i]->Deref();
}
GetEmails_Data::~GetEmails_Data()
{
	for (unsigned i=0; i < emails.Size(); i++)
		emails[i]->Deref();
}
GetActionHistory_Data::~GetActionHistory_Data()
{
	for (unsigned i=0; i < history.Size(); i++)
		history[i]->Deref();
}
void GetActionHistory_Data::Serialize(RakNet::BitStream *bs)
{
	bs->Write(ascendingSort);
	bs->WriteCompressed(history.Size());
	unsigned i;
	for (i=0; i < history.Size(); i++)
		history[i]->Serialize(bs);
}
bool GetActionHistory_Data::Deserialize(RakNet::BitStream *bs)
{
	bool b;
	unsigned historySize;
	bs->Read(ascendingSort);
	b = bs->ReadCompressed(historySize);
	unsigned i;
	AddToActionHistory_Data *data;
	for (i=0; i < historySize; i++)
	{
		data = new AddToActionHistory_Data;
		b=data->Deserialize(bs);
		history.Insert(data);
	}
	return b;
}
void AddToActionHistory_Data::Serialize(RakNet::BitStream *bs)
{
	bs->Write(id.hasUserId);
	bs->Write(id.userId);
	stringCompressor->EncodeString(id.userHandle.c_str(), 4096, bs, 0);
	stringCompressor->EncodeString(actionTime.c_str(), 4096, bs, 0);
	stringCompressor->EncodeString(actionTaken.c_str(), 4096, bs, 0);
	stringCompressor->EncodeString(description.c_str(), 4096, bs, 0);
	stringCompressor->EncodeString(sourceIpAddress.c_str(), 4096, bs, 0);
	bs->Write(creationTime);
}
bool AddToActionHistory_Data::Deserialize(RakNet::BitStream *bs)
{
	bs->Read(id.hasUserId);
	bs->Read(id.userId);
	STDDecodeString(&id.userHandle, 4096, bs, 0);
	STDDecodeString(&actionTime, 4096, bs, 0);
	STDDecodeString(&actionTaken, 4096, bs, 0);
	STDDecodeString(&description, 4096, bs, 0);
	STDDecodeString(&sourceIpAddress, 4096, bs, 0);
	return bs->Read(creationTime);
}
